"""Service资源Markdown写入器模块"""

from typing import Dict, Any, List
from src.writers.base import Writer
from src.utils.markdown_builder import MarkdownBuilder

class ServiceWriter(Writer):
    """
    Service资源Markdown写入器
    负责将提取的Service资源信息写入Markdown文件
    """
    
    def write(self, data: Dict[str, Any], output_path: str) -> None:
        """
        将提取的Service信息写入Markdown
        
        Args:
            data: 提取的Service信息
            output_path: 输出文件路径
        """
        if not data or data.get("kind") != "Service":
            self.logger.warning(f"无效的Service数据: {data.get('name', '未知')}")
            return
        
        # 创建Markdown构建器
        md = self.create_markdown_builder()
        
        # 收集节标题，用于生成目录
        sections = ["基本信息", "选择器", "端口配置", "网络设置", "状态"]
        
        # 标题
        md.header(f"Service: {data.get('name', '未知')}", 1)
        
        # 命名空间
        md.bold("命名空间:").text(f" {data.get('namespace', 'default')}").newline(2)
        
        # 目录
        if len(sections) > 3:  # 只有当节较多时才添加目录
            md.toc(sections)
        
        # 基本信息
        self._write_basic_info(md, data)
        
        # 选择器
        self._write_selector(md, data)
        
        # 端口配置
        self._write_ports(md, data)
        
        # 网络设置
        self._write_network_settings(md, data)
        
        # 状态信息
        self._write_status(md, data)
        
        # 生成Markdown文件
        self.write_markdown(md, output_path)
    
    def _write_basic_info(self, md: MarkdownBuilder, data: Dict[str, Any]) -> None:
        """
        写入基本信息
        
        Args:
            md: Markdown构建器
            data: Service数据
        """
        md.header("基本信息", 2)
        
        # 获取服务类型并翻译
        service_type = data.get("type", "ClusterIP")
        type_map = {
            "ClusterIP": "集群IP",
            "NodePort": "节点端口",
            "LoadBalancer": "负载均衡器",
            "ExternalName": "外部名称"
        }
        service_type_display = type_map.get(service_type, service_type)
        
        # 基本元数据表
        basic_info = {
            "名称": data.get("name", ""),
            "命名空间": data.get("namespace", "default"),
            "创建时间": data.get("creation_timestamp", ""),
            "服务类型": service_type_display
        }
        
        # 外部名称(ExternalName类型特有)
        if service_type == "ExternalName" and "external_name" in data:
            basic_info["外部名称"] = data.get("external_name", "")
        
        # 集群IP
        if "cluster_ip" in data:
            cluster_ip = data.get("cluster_ip", "")
            if cluster_ip == "None":
                basic_info["集群IP"] = "无 (Headless服务)"
            else:
                basic_info["集群IP"] = cluster_ip
                
            # 集群IP列表 (双栈IP支持)
            if "cluster_ips" in data and len(data.get("cluster_ips", [])) > 1:
                basic_info["集群IP列表"] = ", ".join(data.get("cluster_ips", []))
        
        md.dict_table(basic_info)
        
        # 标签和注解
        if data.get("labels"):
            md.header("标签", 3)
            md.dict_table(data.get("labels", {}))
        
        if data.get("annotations"):
            md.header("注解", 3)
            md.dict_table(data.get("annotations", {}))
    
    def _write_selector(self, md: MarkdownBuilder, data: Dict[str, Any]) -> None:
        """
        写入选择器信息
        
        Args:
            md: Markdown构建器
            data: Service数据
        """
        md.header("选择器", 2)
        
        selector = data.get("selector", {})
        if not selector:
            md.paragraph("此服务未配置选择器（可能是外部服务或手动端点）")
            return
        
        md.paragraph("此服务将选择包含以下标签的Pod:")
        md.dict_table(selector)
    
    def _write_ports(self, md: MarkdownBuilder, data: Dict[str, Any]) -> None:
        """
        写入端口配置
        
        Args:
            md: Markdown构建器
            data: Service数据
        """
        md.header("端口配置", 2)
        
        ports = data.get("ports", [])
        if not ports:
            md.paragraph("此服务未配置端口")
            return
        
        # 创建端口表格
        headers = ["名称", "协议", "端口", "目标端口"]
        if data.get("type") == "NodePort":
            headers.append("节点端口")
        if data.get("type") == "LoadBalancer" and any("app_protocol" in port for port in ports):
            headers.append("应用协议")
            
        rows = []
        
        for port in ports:
            row = [
                port.get("name", ""),
                port.get("protocol", "TCP"),
                str(port.get("port", "")),
                str(port.get("target_port", ""))
            ]
            
            # 添加节点端口(如果是NodePort类型)
            if data.get("type") == "NodePort":
                row.append(str(port.get("node_port", "")))
                
            # 添加应用协议(如果有)
            if data.get("type") == "LoadBalancer" and "app_protocol" in port:
                row.append(port.get("app_protocol", ""))
                
            rows.append(row)
        
        md.table(headers, rows)
    
    def _write_network_settings(self, md: MarkdownBuilder, data: Dict[str, Any]) -> None:
        """
        写入网络设置
        
        Args:
            md: Markdown构建器
            data: Service数据
        """
        md.header("网络设置", 2)
        
        network_settings = {}
        
        # 设置服务类型特定的网络信息
        service_type = data.get("type", "ClusterIP")
        
        # 外部IPs
        if "external_ips" in data and data.get("external_ips"):
            network_settings["外部IP"] = ", ".join(data.get("external_ips", []))
        
        # 负载均衡器特定设置
        if service_type == "LoadBalancer":
            # 负载均衡器IP
            if "load_balancer_ip" in data:
                network_settings["负载均衡器IP"] = data.get("load_balancer_ip", "")
                
            # 源范围限制
            if "load_balancer_source_ranges" in data:
                network_settings["源IP范围限制"] = ", ".join(data.get("load_balancer_source_ranges", []))
        
        # 会话亲和性
        if "session_affinity" in data:
            affinity = data.get("session_affinity", "None")
            affinity_map = {
                "None": "无",
                "ClientIP": "客户端IP"
            }
            network_settings["会话亲和性"] = affinity_map.get(affinity, affinity)
            
            # 会话亲和性配置
            if affinity == "ClientIP" and "session_affinity_config" in data:
                config = data.get("session_affinity_config", {})
                if "client_ip" in config and "timeout_seconds" in config.get("client_ip", {}):
                    timeout = config.get("client_ip", {}).get("timeout_seconds", 0)
                    network_settings["会话超时时间"] = f"{timeout}秒"
        
        # 流量策略
        if "traffic_policy" in data:
            policy = data.get("traffic_policy", "")
            policy_map = {
                "Local": "本地",
                "Cluster": "集群"
            }
            network_settings["流量策略"] = policy_map.get(policy, policy)
        
        # IP系列
        if "ip_family" in data:
            family = data.get("ip_family", "")
            family_map = {
                "IPv4": "IPv4",
                "IPv6": "IPv6"
            }
            network_settings["IP协议"] = family_map.get(family, family)
            
            # IP系列策略
            if "ip_family_policy" in data:
                policy = data.get("ip_family_policy", "")
                policy_map = {
                    "SingleStack": "单栈",
                    "PreferDualStack": "优先双栈",
                    "RequireDualStack": "必须双栈"
                }
                network_settings["IP协议策略"] = policy_map.get(policy, policy)
        
        # 输出网络设置表
        if network_settings:
            md.dict_table(network_settings)
        else:
            md.paragraph("使用默认网络设置")
            
        # 外部流量策略(针对NodePort和LoadBalancer)
        if service_type in ["NodePort", "LoadBalancer"] and "external_traffic_policy" in data:
            md.header("外部流量策略", 3)
            
            policy = data.get("external_traffic_policy", "")
            policy_map = {
                "Cluster": "集群级转发(Cluster)",
                "Local": "本地保留客户端源IP(Local)"
            }
            
            policy_desc = policy_map.get(policy, policy)
            md.paragraph(f"外部流量策略: **{policy_desc}**")
            
            # 根据策略提供额外说明
            if policy == "Cluster":
                md.paragraph("请求将分发到集群中的任意后端Pod，可能会丢失客户端源IP")
            elif policy == "Local":
                md.paragraph("请求只会转发到本地节点上的Pod，保留客户端源IP，但可能造成负载不均衡")
    
    def _write_status(self, md: MarkdownBuilder, data: Dict[str, Any]) -> None:
        """
        写入状态信息
        
        Args:
            md: Markdown构建器
            data: Service数据
        """
        md.header("状态", 2)
        
        # LoadBalancer类型服务状态
        if data.get("type") == "LoadBalancer" and "status" in data:
            status = data.get("status", {})
            
            if "load_balancer" in status:
                lb_status = status.get("load_balancer", {})
                
                if "ingress" in lb_status and lb_status.get("ingress"):
                    md.paragraph("负载均衡器已分配以下外部访问点:")
                    
                    headers = ["IP", "主机名"]
                    rows = []
                    
                    for ingress in lb_status.get("ingress", []):
                        rows.append([
                            ingress.get("ip", ""),
                            ingress.get("hostname", "")
                        ])
                    
                    md.table(headers, rows)
                else:
                    md.paragraph("负载均衡器正在配置中，尚未分配外部访问点")
            else:
                md.paragraph("负载均衡器状态信息不可用")
        elif data.get("type") == "ExternalName":
            md.paragraph(f"服务通过DNS CNAME记录指向: **{data.get('external_name', '')}**")
        else:
            # 获取集群IP或无IP(Headless)
            cluster_ip = data.get("cluster_ip", "")
            
            if cluster_ip == "None":
                md.paragraph("此服务为Headless服务，不分配集群IP，使用DNS解析到后端Pod")
                
                # 如果有选择器，说明是标准Headless服务
                if data.get("selector"):
                    md.paragraph("集群内可通过以下DNS记录访问每个Pod:")
                    md.code(f"pod-name.{data.get('name', '')}.{data.get('namespace', 'default')}.svc.cluster.local")
            else:
                # 普通ClusterIP或NodePort服务
                md.paragraph(f"集群内可通过以下方式访问:")
                
                with md.list() as lst:
                    lst.item(f"集群IP: **{cluster_ip}**")
                    lst.item(f"服务名: **{data.get('name', '')}**")
                    lst.item(f"FQDN: **{data.get('name', '')}.{data.get('namespace', 'default')}.svc.cluster.local**")
                
                # 如果是NodePort类型，添加访问说明
                if data.get("type") == "NodePort":
                    md.paragraph("集群外可通过以下方式访问:")
                    md.code(f"<任意节点IP>:<节点端口>")